{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 奇怪的现象\n",
    "\n",
    "在计算机内部float比较是很坑爹的事情。比方说,0.1+0.2得到的结果竟然不是0.3?\n",
    "\n",
    "```javascript\n",
    ">>> 0.1+0.2\n",
    "0.30000000000000004\n",
    "```\n",
    "\n",
    "复制\n",
    "\n",
    "# 为什么会出现如此傻的结果呢？\n",
    "\n",
    "[这篇文章](https://floating-point-gui.de/basic/)做了详细的解释，简单的来说就是计算机里面的数字是由二进制保存的，在计算机内部有些数字不能准确的保存，于是就保存一个最靠近的数字。\n",
    "\n",
    "在十进制中也会存在这样的问题，数字不能准确地表示像1/3这样的数字，所以你必须舍入到0.33之类的东西 - 你不要指望0.33 + 0.33 + 0.33加起来就是1。\n",
    "\n",
    "因此我们在比较两个float是否相等时，不能仅仅依靠 == 来进行判断，而是当他们两者的差小于一个我们可以容忍的小值时，就可以认为他们就是相等的。\n",
    "\n",
    "# Python中是如何解决的？\n",
    "\n",
    "各种语言中都有类似的处理方式，python中是这样处理的？ StackOverFlow有类似的问题: [what-is-the-best-way-to-compare-floats-for-almost-equality-in-python](https://stackoverflow.com/questions/5595425/what-is-the-best-way-to-compare-floats-for-almost-equality-in-python)\n",
    "\n",
    "## 简单粗暴的判断方法\n",
    "\n",
    "```\n",
    "return abs(f1 - f2) <= allowed_error\n",
    "```\n",
    "\n",
    "\n",
    "python3.5之后,PEP485提案中已给出了解决方案。 使用math.isclose方法，传入需要比较的两个数和可以接受的精度差值即可。\n",
    "\n",
    "## PEP 485: A function for testing approximate equality\n",
    "\n",
    "> PEP 485 adds the math.isclose() and cmath.isclose() functions which tell whether two values are approximately equal or “close” to each other. Whether or not two values are considered close is determined according to given absolute and relative tolerances. Relative tolerance is the maximum allowed difference between isclose arguments, relative to the larger absolute value:\n",
    "\n",
    "### math.isclose 使用方法\n",
    "\n",
    "```javascript\n",
    ">>> import math\n",
    ">>> a = 5.0\n",
    ">>> b = 4.99998\n",
    ">>> math.isclose(a, b, rel_tol=1e-5)\n",
    "True\n",
    ">>> math.isclose(a, b, rel_tol=1e-6)\n",
    "False\n",
    "It is also possible to compare two values using absolute tolerance,\n",
    " which must be a non-negative value:\n",
    "\n",
    ">>> import math\n",
    ">>> a = 5.0\n",
    ">>> b = 4.99998\n",
    ">>> math.isclose(a, b, abs_tol=0.00003)\n",
    "True\n",
    ">>> math.isclose(a, b, abs_tol=0.00001)\n",
    "False\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}